package com.zdw.oauth.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdw.common.constant.common.CommonConstants;
import com.zdw.common.exception.GlobalException;
import com.zdw.oauth.config.international.InternationalUtils;
import com.zdw.oauth.dto.UserAddDto;
import com.zdw.oauth.dto.UserSelectDto;
import com.zdw.oauth.dto.UserUpdDto;
import com.zdw.oauth.entity.UserEntity;
import com.zdw.oauth.entity.UserRoleEntity;
import com.zdw.oauth.mapper.UserMapper;
import com.zdw.oauth.mapper.UserRoleMapper;
import com.zdw.oauth.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author 卓德文
 * @since 2023-01-04
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Resource
    private UserRoleMapper userRoleMapper;

    /**
     * 新增用户
     *
     * @param dto
     * @return
     */
    @Override
    public boolean add(UserAddDto dto) {
        //1.查询是否已存在用户(账号、手机号码)
        UserEntity entity = this.selectByAccountOrPhone(dto.getAccount(), dto.getPhone(), null);
        if (ObjectUtil.isNotEmpty(entity) && StrUtil.isNotBlank(entity.getAccount())) {
            throw new GlobalException(InternationalUtils.getInternational("user.exist"));
        }

        //2.新增
        UserEntity userEntity = BeanUtil.copyProperties(dto, UserEntity.class);
        Date date = new Date();
        Integer loginId = Integer.parseInt(StpUtil.getTokenInfo().getLoginId().toString());
        userEntity.setCreator(loginId);
        userEntity.setModifier(loginId);
        userEntity.setCreateTime(date);
        userEntity.setUpdateTime(date);
        userEntity.setPassword(CommonConstants.USER_DEFAULT_PASSWORD);
        return this.baseMapper.insert(userEntity) > 0;
    }

    /**
     * 编辑用户
     *
     * @param dto
     * @return
     */
    @Override
    public boolean update(UserUpdDto dto) {
        //1.查询是否已存在用户(账号、手机号码)
        UserEntity entity = this.selectByAccountOrPhone(dto.getAccount(), dto.getPhone(), dto.getId());
        if (ObjectUtil.isNotEmpty(entity) && StrUtil.isNotBlank(entity.getAccount())) {
            throw new GlobalException(InternationalUtils.getInternational("user.exist"));
        }

        //2.编辑
        UserEntity userEntity = BeanUtil.copyProperties(dto, UserEntity.class);
        userEntity.setModifier(Integer.parseInt(StpUtil.getTokenInfo().getLoginId().toString()));
        userEntity.setUpdateTime(new Date());
        return this.baseMapper.updateById(userEntity) > 0;
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     */
    @Override
    public boolean delete(int id) {
        //1.删除用户
        int delCount = this.baseMapper.deleteById(id);

        //2.删除用户-角色的关联关系
        if (delCount > 0) {
            Wrapper<UserRoleEntity> wrapper = Wrappers.lambdaQuery(UserRoleEntity.class)
                    .eq(UserRoleEntity::getUserId, id);
            userRoleMapper.delete(wrapper);
        }
        return delCount > 0;
    }

    /**
     * 查询用户信息
     *
     * @param id
     * @return
     */
    @Override
    public UserEntity select(int id) {
        return this.baseMapper.selectById(id);
    }

    /**
     * 分页查询用户列表
     *
     * @param dto
     * @return
     */
    @Override
    public IPage<UserEntity> page(UserSelectDto dto) {
        IPage<UserEntity> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Wrapper<UserEntity> wrapper = Wrappers.lambdaQuery(UserEntity.class)
                .eq(StrUtil.isNotBlank(dto.getAccount()), UserEntity::getAccount, dto.getAccount())
                .like(StrUtil.isNotBlank(dto.getName()), UserEntity::getName, dto.getName())
                .eq(StrUtil.isNotBlank(dto.getPhone()), UserEntity::getPhone, dto.getPhone())
                .eq(ObjectUtil.isNotNull(dto.getState()), UserEntity::getState, dto.getState());
        return this.baseMapper.selectPage(page, wrapper);
    }

    /**
     * 根据电话号码查询用户信息(用于手机登陆)
     *
     * @return
     */
    @Override
    public UserEntity selectByPhone(String phone) {
        Assert.notEmpty(phone, InternationalUtils.getInternational("oauth.phone.empty"));
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserEntity::getPhone, phone)
                .eq(UserEntity::getState, CommonConstants.USER_STATE_ABLE)
                .last(" limit 1");
        return this.baseMapper.selectOne(queryWrapper);
    }

    /**
     * 根据账号查询用户信息(用于账号登陆)
     *
     * @return
     */
    @Override
    public UserEntity selectByAccount(String account) {
        Assert.notEmpty(account, InternationalUtils.getInternational("oauth.account.empty"));
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserEntity::getAccount, account)
                .eq(UserEntity::getState, CommonConstants.USER_STATE_ABLE)
                .last(" limit 1");
        return this.baseMapper.selectOne(queryWrapper);
    }

    /**
     * 根据账号或手机号码查询用户
     *
     * @return
     */
    private UserEntity selectByAccountOrPhone(String account, String phone, Integer id) {
        Assert.notEmpty(phone, InternationalUtils.getInternational("oauth.phone.empty"));
        Assert.notEmpty(account, InternationalUtils.getInternational("oauth.account.empty"));
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(StrUtil.isNotBlank(account), UserEntity::getAccount, account)
                .or()
                .eq(StrUtil.isNotBlank(phone), UserEntity::getPhone, phone)
                .ne(ObjectUtil.isNotEmpty(id), UserEntity::getId, id)
                .last(" limit 1");
        return this.baseMapper.selectOne(queryWrapper);
    }
}
